/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package Negocio;

/**
 *
 * @author Analia
 */
import Compilador.Scanner;
import Compilador.Linea;
import Compilador.Parser;
import Compilador.Token;
import Datos.consultas;


import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.Socket;

import java.util.LinkedList;
import java.util.StringTokenizer;


public class POP3
{
    private Configuracion configuracion;
    private Linea line;
    private Scanner scan;
    private Parser parser;
    private Token tokenComando;
    private LinkedList  datos;

    
    private consultas procesadorCosultas;
    private SMTP correo;


    private BufferedReader _bufferedReaderUSER;
    private Socket _socket;
    private InputStream _inputStreamPOP;
    private BufferedReader _bufferedReaderFROM;
    private OutputStream _outputStreanPOP;
    private PrintWriter _printWriterTO;

    private String lineaTelnet;

   
    public POP3(Configuracion configuracion)
    {
        this.configuracion =  configuracion;
        conexionPOP3();
        line    = new Linea();
        scan  = new Scanner();
        parser   = new Parser();
        
        correo   = new SMTP(configuracion);
        this.procesadorCosultas = new consultas();
    }


    public void conexionPOP3()
    {
        try
        {
            System.out.println("Conectando al puerto 110.....(POP3)\n");

            _bufferedReaderUSER = new BufferedReader(new InputStreamReader(System.in));
            System.out.println("Configurando Conexion.... 11 \n");
            _socket = new Socket(configuracion.getDominio(), configuracion.getPuertoPOP());
            System.out.println("Configurando Conexion.... 22 \n");

            
            _inputStreamPOP = _socket.getInputStream();
            System.out.println("Configurando Conexion.... 33 \n");
            _bufferedReaderFROM = new BufferedReader(new InputStreamReader(_inputStreamPOP));

            _outputStreanPOP = _socket.getOutputStream();
            _printWriterTO = new PrintWriter(new OutputStreamWriter(_outputStreanPOP));

            String linea  = "";

            linea = _bufferedReaderFROM.readLine();
            _printWriterTO.println("USER " + configuracion.getCorreo());
            _printWriterTO.flush();
            System.out.println("        Usuario  : "+configuracion.getCorreo()+"\n");

            linea = _bufferedReaderFROM.readLine();
            _printWriterTO.println("PASS " + configuracion.getContrasena());
            _printWriterTO.flush();
            System.out.println("        Contraseña : "+configuracion.getContrasena()+"\n");

            linea = _bufferedReaderFROM.readLine();

            System.out.println("CONECTADO A POP3\n");

        }
        catch(Exception e)
        {
            System.out.print("ERROR: No se pudo establecer la conexion al puerto 110; La causa fue : "+e.getCause());
        }
    }


    public void readMessages()
    {
        conexionPOP3();

        String linea = "";
        String mail_from="";
        String subject = "";
        String comando = "";
        String from    = "";
        String email   = "";

        int numberMessages = 0;     int borravacio=0;

        try
        {
            numberMessages = telnetStat();

            for (int i= 1; i<= numberMessages; i++)
            {
                borravacio=i;
                telnetRetr(i);
        
                boolean activoFrom = true;
                int iii =0;                                                         //&&(!email.equals(("")))
                while(!(linea = _bufferedReaderFROM.readLine()).equalsIgnoreCase("."))
                {
                   System.out.println("inc  : "+iii);
                   System.out.println("inc linea  : "+linea);
                   if (!(linea.equals(""))&&(linea.length()>=7))
                   {
                        if (linea.length()>=11)
                        {
                            from   = getFrom(linea);
                            
                            if (from.equalsIgnoreCase("Return-Path")&& activoFrom)
                            {
                               email = getEmail(linea);
                               
                               activoFrom = false;
                               System.out.println("El remitente es: " + email + "\n");
                            }
                        }
                        subject = getSubject(linea);
                
                        if (subject.equalsIgnoreCase("subject"))
                        {
                            comando =getComando(linea);

                            System.out.println("El comando es: " + comando + "\n");
                        }
                   }
                   iii++;
                }
                System.out.println("\n----------------------- lista de personas existe Gustavo Tantani Mamani ---------------01");
                mail_from = configuracion.getCorreo()+"@"+ configuracion.getDominio();
                System.out.println("\n----------------------- lista de personas existe Gustavo Tantani Mamani ---------------0");
                parser(comando);
                System.out.println("\n----------------------- lista de personas existe Gustavo Tantani Mamani ---------------1");

                //if(tokenComando.getToken().equals(Token.nombreToken.LISTPERSONAS)  )
                System.out.println("nombre to : "+Token.nombreToken.REGISTRAR_USUARIO+" asd  :"+tokenComando.getToken());
                if(tokenComando.getToken() != null)
                if (procesadorCosultas.clienteValido(email) || tokenComando.getToken().equals(Token.nombreToken.REGISTRAR_USUARIO) )
                {
                        System.out.println("\n------------ PREPARANDO RESPUESTA -------asda");
                        procesadorCosultas.setEmail(email);
                        procesarDatos();
                        System.out.println("\n------------ PREPARANDO RESPUESTA -------");
                        correo.conexionSMTP();
                        correo.enviar(mail_from,email,comando,procesadorCosultas.getRespuesta());
                        System.out.println("\n -------- SOLICITUD RESPONDIDA --------");
                        correo.quit();

                }
                else
                {
                       String errorRegistro = "ERROR: Usted todavia no se ha registrado, en este email le indicamos como hacerlo";
                       System.out.println("nombre to 0: "+errorRegistro);
                       correo.conexionSMTP();
                       System.out.println("\n----------------------- lista de personas existe Gustavo Tantani Mamani ---------------2");
                       System.out.println("nombre to 1: "+mail_from);
                       System.out.println("nombre to 2: "+email);
                       correo.enviar(mail_from,email,errorRegistro,procesadorCosultas.errorRegistro());
                       System.out.println("\n----------------------- lista de personas existe Gustavo Tantani Mamani ---------------3");
                       correo.quit();
             
                }
               telnetDele(i);  
            } 
        }
        catch(Exception e)
        {
            System.out.println("ERROR: No se pudieron leer los mensajes; La causa es " + e.getCause());
            telnetDele(borravacio);
            correo.conexionSMTP();
            correo.enviar(mail_from,email,"Error de Subject, Revise la AYUDA",procesadorCosultas.errorRegistro());
            correo.quit();
        }

       telnetQuit();
    }


    private int getCountMessages(String linea)
    {
        try
        {
            String auxlinea = linea.trim();
            auxlinea = auxlinea.substring(4,auxlinea.length());
            auxlinea = auxlinea.trim();

            auxlinea = auxlinea.substring(0,auxlinea.indexOf(" "));
            return Integer.parseInt(auxlinea);
        }
        catch(Exception e)
        {
            System.out.println("ERROR al contar los correos ; La causa es " + e.getCause());
            return -1;
        }
    }

    private String getSubject(String linea)
    {
        try
        {
            String auxlinea = linea.trim();
            auxlinea = auxlinea.substring(0,7);
            return auxlinea;
        }
        catch(Exception e)
        {
            System.out.println("ERROR: No hay subject  ; La causa es " + e.getCause());
            return null;
        }
    }

    private String getComando(String linea)
    {
        try
        {
            String auxlinea = linea.trim();
            auxlinea = auxlinea.substring(9,auxlinea.length());

            return auxlinea;
        }
        catch(Exception e)
        {
            System.out.println("ERROR: El SUBJECT no tiene un comando valido  ; La causa es " + e.getCause());
            return null;
        }
    }

    private String getFrom(String linea)
    {
        try
        {
            String auxlinea = linea.trim();
            auxlinea = auxlinea.substring(0,11);
            return auxlinea;
        }
        catch(Exception e)
        {
            System.out.println("ERROR: No hay email  ; La causa es " + e.getCause());
            return null;
        }
    }

    private String getEmail(String linea)
    {
        try
        {
            String auxlinea = linea.trim();
            auxlinea = auxlinea.substring(14,auxlinea.length());
            StringTokenizer auxEmail = new StringTokenizer(auxlinea,"<>");
            auxlinea = auxEmail.nextToken();
            return auxlinea;
        }
        catch(Exception e)
        {
            System.out.println("ERROR: No se pudo leer el contenido  ; La causa es " + e.getCause());
            return null;
        }
    }

    public int telnetStat()
    {

        try
        {
            _printWriterTO.println("STAT");
            _printWriterTO.flush();
            lineaTelnet =_bufferedReaderFROM.readLine();
            System.out.println("Esta es la Linea de STAT : " + lineaTelnet + "\n");
            int numMessages = getCountMessages(lineaTelnet);
            System.out.println("El numero de mensajes es: " + numMessages + "\n");
            return numMessages;
        }
        catch(Exception e)
        {
            System.out.println("ERROR en el comando STAT ; La causa es "+e.getCause());
            return -1;
        }
    }

    public void telnetRetr(int numCorreo)
    {
        System.out.println("Leyendo el correo: " + numCorreo+"\n");
        _printWriterTO.println("RETR " + numCorreo);
        _printWriterTO.flush();
    }

    public void telnetDele(int numCorreo)
    {
        try
        {
            _printWriterTO.println("DELE "+numCorreo);
            _printWriterTO.flush();
            lineaTelnet = _bufferedReaderFROM.readLine();
            System.out.println("Esta es la Linea de DELE : " + lineaTelnet + "\n");

        } catch (Exception  e)
        {
            System.out.println("ERROR en el comando DELE ; La causa es "+e.getCause());
        }

    }

    public String telnetList()
    {
        try
        {
            _printWriterTO.println("LIST");
            _printWriterTO.flush();

            String linea = "";
            String listado = "";
            while(!(linea = _bufferedReaderFROM.readLine()).equalsIgnoreCase("."))
            {
                listado = listado.concat("\t"+linea + "\n");
            }
            return listado;
        }
        catch(Exception e)
        {
            System.out.println("ERROR en el comando LIST ; La causa es "+e.getCause());
            return null;
        }
    }

    public String telnetContenido(int numCorreo)
    {
        try
        {
            telnetRetr(numCorreo);

            String linea = "";
            String contenido = "";
            while(!(linea = _bufferedReaderFROM.readLine()).equalsIgnoreCase("."))
            {
                contenido = contenido.concat(linea + "\n");
            }
            return contenido;
        }
        catch (Exception e)
        {
            System.out.println("ERROR: El Nº de correo especificado, no existe  ; La causa es" + e.getCause());
            return null;
        }
    }

    public void telnetQuit()
    {
        _printWriterTO.println("QUIT");
        _printWriterTO.flush();
    }

    public void desconectar()
    {
        try
        {
            _printWriterTO.close();
            _bufferedReaderFROM.close();
            _socket.close();
        }
        catch(Exception e)
        {
            System.out.println("ERROR al desconectarse por TELNET ; La causa es " + e.getCause());
        }
    }

    public void parser(String subject)
    {
        line.resetearPuntero();
        line.setLinea(subject);
        scan.setLinea(line);
        scan.avanzar();
        parser.setScanner(scan);
        parser.inicio();
        parser.programa();
        tokenComando = (Token)parser.getComando();
        datos = (LinkedList)parser.getDatos();
  
        procesadorCosultas.setSubject(subject);
    }

    public void procesarDatos()
    {
        System.out.println("Se proceso bien 1");
        enviarServicio(tokenComando,datos);
        System.out.println("Se proceso bien 2");
        procesadorCosultas.ejecutarServicio();

        System.out.println("Se proceso bien 3");
    }

    private void enviarServicio(Token tokenComando, LinkedList datos)
    {
        //procesarBD.setDatos(datos);
        procesadorCosultas.setDatos(datos);
        switch(tokenComando.getToken())
        {
            case AYUDA                      : procesadorCosultas.setServicio(procesadorCosultas.getServicio().AYUDA); break;
            case REGISTRAR_USUARIO          : procesadorCosultas.setServicio(procesadorCosultas.getServicio().REGISTRAR_USUARIO);break;
            case REGISTRAR_DOCENTE          : procesadorCosultas.setServicio(procesadorCosultas.getServicio().REGISTRAR_DOCENTE);break;
            case REGISTRAR_ALUMNO           : procesadorCosultas.setServicio(procesadorCosultas.getServicio().REGISTRAR_ALUMNO);break;
            case REGISTRAR_DIRECTOR         : procesadorCosultas.setServicio(procesadorCosultas.getServicio().REGISTRAR_DIRECTOR);break;
            case REGISTRAR_MATERIA         : procesadorCosultas.setServicio(procesadorCosultas.getServicio().REGISTRAR_MATERIA);break;
            case REGISTRAR_GRUPO         : procesadorCosultas.setServicio(procesadorCosultas.getServicio().REGISTRAR_GRUPO);break;
            case RE_ALUMNOMATERIA         : procesadorCosultas.setServicio(procesadorCosultas.getServicio().RE_ALUMNOMATERIA);break;
            case RE_DOCENTEMATERIA         : procesadorCosultas.setServicio(procesadorCosultas.getServicio().RE_DOCENTEMATERIA);break;
            case RE_EXAMEN         : procesadorCosultas.setServicio(procesadorCosultas.getServicio().RE_EXAMEN);break;
            case RE_PROGRAMACION         : procesadorCosultas.setServicio(procesadorCosultas.getServicio().RE_PROGRAMACION);break;
            case RE_TIPOPREGUNTA         : procesadorCosultas.setServicio(procesadorCosultas.getServicio().RE_TIPOPREGUNTA);break;
            case RE_PREGUNTA         : procesadorCosultas.setServicio(procesadorCosultas.getServicio().RE_PREGUNTA);break;
            case RE_RESPUESTA         : procesadorCosultas.setServicio(procesadorCosultas.getServicio().RE_RESPUESTA);break;




            //case RESERVAS_CLIENTE               : procesadorCosultas.setServicio(procesadorCosultas.getServicio().RESERVAS_CLIENTE); break;
            //case RESERVAR_PRODUCTO          : procesadorCosultas.setServicio(procesadorCosultas.getServicio().RESERVAR_PRODUCTO); break;
            //case ESTADISTICAS           : procesadorCosultas.setServicio(procesadorCosultas.getServicio().ESTADISTICAS); break;
            //case INFORMACION_PRODUCTO   : procesadorCosultas.setServicio(procesadorCosultas.getServicio().INFORMACION_PRODUCTO); break;
            //case COTIZACION             : procesadorCosultas.setServicio(procesadorCosultas.getServicio().COTIZACION); break;
            //case DETALLE_RESERVAS       : procesadorCosultas.setServicio(procesadorCosultas.getServicio().DETALLE_RESERVAS); break;
            //case LISTAR_PROMOCION       : procesadorCosultas.setServicio(procesadorCosultas.getServicio().LISTAR_PROMOCION); break;
            //case LISTAR_PRODUCTO          : procesadorCosultas.setServicio(procesadorCosultas.getServicio().LISTAR_PRODUCTO); break;
            //case LISTAR_PEDIDOS           : procesadorCosultas.setServicio(procesadorCosultas.getServicio().LISTAR_PEDIDOS); break;
            //case LISTAR_CLIENTES          : procesadorCosultas.setServicio(procesadorCosultas.getServicio().LISTAR_CLIENTES); break;

            //case LISTAR_RESCLI   : procesadorCosultas.setServicio(procesadorCosultas.getServicio().LISTAR_RESCLI); break;

            //case VER_OFERTAS            : procesadorCosultas.setServicio(procesadorCosultas.getServicio().VER_OFERTAS); break;
            //case REGISTRAR                : procesadorCosultas.setServicio(procesadorCosultas.getServicio().REGISTRAR); break;

            // bolsa de trabajo
            //case OFERTA_GENERAL             : procesadorCosultas.setServicio(procesadorCosultas.getServicio().OFERTA_GENERAL); break;
            //case REGISTRAR_OFERTA           : procesadorCosultas.setServicio(procesadorCosultas.getServicio().REGISTRAR_OFERTA);break;
            //case ELIMINAR_OFERTA          : procesadorCosultas.setServicio(procesadorCosultas.getServicio().ELIMINAR_OFERTA);break;
            //case MODIFICAR_FECHA_LIMITE          : procesadorCosultas.setServicio(procesadorCosultas.getServicio().MODIFICAR_FECHA_LIMITE);break;


            
            //case LISTAR_USUARIOS          : procesadorCosultas.setServicio(procesadorCosultas.getServicio().LISTAR_USUARIOS);break;
            //case LISTAR_AREA          : procesadorCosultas.setServicio(procesadorCosultas.getServicio().LISTAR_AREA);break;
            //case LISTAR_EMPRESA          : procesadorCosultas.setServicio(procesadorCosultas.getServicio().LISTAR_EMPRESA);break;
            //case LISTAR_TITULO          : procesadorCosultas.setServicio(procesadorCosultas.getServicio().LISTAR_TITULO);break;
            //case BUSCAR_OFERTA          : procesadorCosultas.setServicio(procesadorCosultas.getServicio().BUSCAR_OFERTA);break;
            //case LISTAR_OFERTAS          : procesadorCosultas.setServicio(procesadorCosultas.getServicio().LISTAR_OFERTAS);break;

            // fin bolsa


            default                       : procesadorCosultas.setServicio(procesadorCosultas.getServicio().ERROR);
        }

    }

}
